GtkCssProvider: Load themes from versioned directories
authorMatthias Clasen <mclasen@redhat.com>
Thu, 13 Nov 2014 00:22:55 +0000 (19:22 -0500)
committerMatthias Clasen <mclasen@redhat.com>
Thu, 13 Nov 2014 00:22:55 +0000 (19:22 -0500)
Look for themes in $prefix/themes/$name/gtk-$version/ (for
version = 3.16, 3.14, ...), before using the old location
$prefix/themes/$name/gtk-3.0/. This gives theme authors a
way to support multiple versions of GTK+ 3 with separate
css files.

gtk/gtkcssprovider.c

index 8b495d219bf247374606cefaddd51ca47987ac9d..daadf04b740ebd50944541df40047b541592aa7e 100644 (file)
@@ -44,6 +44,7 @@
 #include "gtkmarshalers.h"
 #include "gtkprivate.h"
 #include "gtkintl.h"
+#include "gtkversion.h"
 
 /**
  * SECTION:gtkcssprovider
@@ -2947,7 +2948,6 @@ _gtk_css_provider_get_theme_dir (void)
   gchar *path;
 
   var = g_getenv ("GTK_DATA_PREFIX");
-
   if (var)
     path = g_build_filename (var, "share", "themes", NULL);
   else
@@ -2956,46 +2956,92 @@ _gtk_css_provider_get_theme_dir (void)
   return path;
 }
 
+#if (GTK_MINOR_VERSION % 2)
+#define MINOR (GTK_MINOR_VERSION + 1)
+#else
+#define MINOR GTK_MINOR_VERSION
+#endif
+
+/*
+ * Look for
+ * $dir/$subdir/gtk-3.16/gtk-$variant.css
+ * $dir/$subdir/gtk-3.14/gtk-$variant.css
+ *  ...
+ * $dir/$subdir/gtk-3.0/gtk-$variant.css
+ * and return the first found file.
+ * We don't check versions before 3.14,
+ * since those GTK+ versions didn't have
+ * the versioned loading mechanism.
+ */
 static gchar *
-_gtk_css_find_theme (const gchar *name,
-                     const gchar *variant)
-{
-  gchar *subpath;
+_gtk_css_find_theme_dir (const gchar *dir,
+                         const gchar *subdir,
+                         const gchar *name,
+                         const gchar *variant)
+{
+  gchar *file;
+  gchar *base;
+  gchar *subsubdir;
+  gint i;
   gchar *path;
 
   if (variant)
-    subpath = g_strdup_printf ("gtk-3.0" G_DIR_SEPARATOR_S "gtk-%s.css", variant);
+    file = g_strconcat ("gtk-", variant, ".css", NULL);
   else
-    subpath = g_strdup ("gtk-3.0" G_DIR_SEPARATOR_S "gtk.css");
+    file = g_strdup ("gtk.css");
 
-  /* First look in the user's config directory */
-  path = g_build_filename (g_get_user_data_dir (), "themes", name, subpath, NULL);
-  if (!g_file_test (path, G_FILE_TEST_EXISTS))
+  if (subdir)
+    base = g_build_filename (dir, subdir, name, NULL);
+  else
+    base = g_build_filename (dir, name, NULL);
+
+  for (i = MINOR; i >= 0; i = i - 2)
     {
-      g_free (path);
-      /* Next look in the user's home directory
-       */
-      path = g_build_filename (g_get_home_dir (), ".themes", name, subpath, NULL);
-      if (!g_file_test (path, G_FILE_TEST_EXISTS))
-        {
-          gchar *theme_dir;
+      if (i < 14)
+        i = 0;
 
-          g_free (path);
+      subsubdir = g_strdup_printf ("gtk-3.%d", i);
+      path = g_build_filename (base, subsubdir, file, NULL);
+      g_free (subsubdir);
 
-          /* Finally, try in the default theme directory */
-          theme_dir = _gtk_css_provider_get_theme_dir ();
-          path = g_build_filename (theme_dir, name, subpath, NULL);
-          g_free (theme_dir);
+      if (g_file_test (path, G_FILE_TEST_EXISTS))
+        break;
 
-          if (!g_file_test (path, G_FILE_TEST_EXISTS))
-            {
-              g_free (path);
-              path = NULL;
-            }
-        }
+      g_free (path);
+      path = NULL;
     }
 
-  g_free (subpath);
+  g_free (file);
+  g_free (base);
+
+  return path;
+}
+
+#undef MINOR
+
+static gchar *
+_gtk_css_find_theme (const gchar *name,
+                     const gchar *variant)
+{
+  gchar *path;
+  const gchar *var;
+
+  /* First look in the user's config directory */
+  path = _gtk_css_find_theme_dir (g_get_user_data_dir (), "themes", name, variant);
+  if (path)
+    return path;
+
+  /* Next look in the user's home directory */
+  path = _gtk_css_find_theme_dir (g_get_home_dir (), ".themes", name, variant);
+  if (path)
+    return path;
+
+  /* Finally, try in the default theme directory */
+  var = g_getenv ("GTK_DATA_PREFIX");
+  if (!var)
+    var = _gtk_get_data_prefix ();
+
+  path = _gtk_css_find_theme_dir (var, "share" G_DIR_SEPARATOR_S "themes", name, variant);
 
   return path;
 }
@@ -3017,7 +3063,7 @@ _gtk_css_provider_load_named (GtkCssProvider *provider,
                               const gchar    *name,
                               const gchar    *variant)
 {
-  gchar *subpath, *path;
+  gchar *path;
   gchar *resource_path;
 
   g_return_if_fail (GTK_IS_CSS_PROVIDER (provider));